function render(template, context) {

    //被转义的的分隔符 { 和 } 不应该被渲染，分隔符与变量之间允许有空白字符
    var tokenReg = /(\\)?\{([^\{\}\\]+)(\\)?\}/g;

    return template.replace(tokenReg, function (word, slash1, token, slash2) {
        //如果有转义的\{或\}替换转义字符
        if (slash1 || slash2) {
            return word.replace('\\', '');
        }

        // 切割 token ,实现级联的变量也可以展开
        var variables = token.replace(/\s/g, '').split('.');
        var currentObject = context;
        var i, length, variable;

        for (i = 0, length = variables.length; i < length; ++i) {
            variable = variables[i];
            currentObject = currentObject[variable];
            // 如果当前索引的对象不存在，则直接返回空字符串。
            if (currentObject === undefined || currentObject === null) return '';
        }
        return currentObject;
    })
}

String.prototype.render = function (context) {
    return render(this, context);
};

var result = "{greeting}! My name is { author.name }.".render({
    greeting: "Hi",
    author: {
        name: "hsfzxjy"
    }
});
console.log(result);
// Hi! My name is hsfzxjy.

var Person = function (name) {
    this.name = name;
};

Person.prototype.age = 13;

var p = new Person('haha');
console.log(p.age);
// p.sex = 'man';

console.log(Object.keys(p));
console.log(p.hasOwnProperty('age'));
console.log('age' in p);

// for(var key in p){
//     console.log(key);
// }

Object.keys2 = function (obj) {
    var arr = [];
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            arr.push(key);
        }
    }
    return arr;
};


console.log(Object.keys2(p));

//考察词法环境
{
    var name = 'window'
    function test(cb, val) {
        var name = 'in'
        console.log('-------test-------', val)
        cb()
        return val
    }
    function outf() {
        var time = test(function () {
            console.log('outf--------', name)
        }, 100);
        var name = 'out';
    }
    outf()
}